/*
家人们，又有一个问题了：
如果出现effectFn即读取了值，又修改了值
effect(()=>{
  obj.data++
})
执行effect，effectFn执行，读取obj.data, track操作
effectFn仍然在执行，然后obj.data + 1 赋值给obj.data， 此时执行trigger， 将之前track到的effectFn取出又执行
*/
const bucket = new WeakMap()

// 注册effect回调
let activeEffect
const effectStack = [] // 新增 effect栈!!!!!!!!!!!!
function effect(fn) {
  const effectFn = () => {
    cleanup(effectFn)
    activeEffect = effectFn
    effectStack.push(effectFn) // fn执行，调用track, 读取activeEffect, 先入栈
    fn()
    effectStack.pop() // 当前effectFn已经注册完毕, 弹出
    activeEffect = effectStack[effectStack.length - 1]
  }
  effectFn.deps = []
  effectFn()
}

function cleanup(effectFn) {
  for (let i = 0; i < effectFn.deps.length; i++) {
    const deps = effectFn.deps[i]
    deps.delete(effectFn)
  }
  effectFn.deps.length = 0
}

function track(target, key) {
  if (!activeEffect) return
  let depsMap = bucket.get(target)
  if (!depsMap) bucket.set(target, (depsMap = new Map()))
  let deps = depsMap.get(key)
  if (!deps) depsMap.set(key, (deps = new Set()))
  deps.add(activeEffect)
  activeEffect.deps.push(deps)
}

function trigger(target, key) {
  const depsMap = bucket.get(target)
  if (!depsMap) return
  const deps = depsMap.get(key)
  if (!deps) return
  // const effectsToRun = new Set(deps)
  /*
    问题就是这个effectFn引起的，不能直接执行，要判断是否effectFn是否是当前正在执行的activeEffect
  */
  const effectsToRun = new Set()
  deps.forEach((effectFn) => {
    if (effectFn !== activeEffect) {
      effectsToRun.add(effectFn)
    }
  })
  effectsToRun.forEach((effectFn) => effectFn())
}

const data = { count: 0 }

const obj = new Proxy(data, {
  get(target, key) {
    track(target, key)
    return Reflect.get(target, key)
  },
  set(target, key, val) {
    Reflect.set(target, key, val)
    trigger(target, key)
    return true
  },
})
effect(() => {
  obj.count++
  console.log('current count:', obj.count)
})

setTimeout(() => {
  obj.count++
}, 1000)
